import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:state_manage/timer/ticker.dart';
import './bloc.dart';

/// 定时器Bloc
class TimerBloc extends Bloc<TimerEvent, TimerState> {
  /// 定时器时间
  final int _duration = 60;
  /// 定时器数据流
  final Ticker _ticker;
  // 流订阅
  StreamSubscription<int> _tickerSubscription;

  TimerBloc({@required Ticker ticker})
      : assert(ticker != null),
        _ticker = ticker;

  /// 初始化状态
  @override
  TimerState get initialState => Ready(_duration);

  @override
  Stream<TimerState> mapEventToState(
    TimerEvent event,
  ) async* {
    print('$event');
    if (event is Start) {
      yield* _mapStartToState(event);
    } else if (event is Tick) {
      yield* _mapTickToState(event);
    } else if (event is Pause) {
      yield* _mapPauseToState(event);
    } else if (event is Resume) {
      yield* _mapResumeToState(event);
    } else if (event is Reset) {
      yield* _mapResetToState(event);
    }
  }

  @override
  Future<void> close() {
    _tickerSubscription?.cancel();
    return super.close();
  }

  /// 处理开始事件
  Stream<TimerState> _mapStartToState(Start start) async* {
    // 运行状态
    yield Running(start.duration);
    // 取消订阅
    _tickerSubscription?.cancel();
    // 创建订阅
    _tickerSubscription =
        _ticker.tick(ticks: start.duration).listen((duration) {
      add(Tick(duration: duration));
    });
  }

  /// 处理定时器事件
  Stream<TimerState> _mapTickToState(Tick tick) async* {
    yield tick.duration > 0 ? Running(tick.duration) : Finished();
  }

  /// 处理暂停事件
  Stream<TimerState> _mapPauseToState(Pause pause) async* {
    if (state is Running) {
      _tickerSubscription?.pause();
      yield Paused(state.duration);
    }
  }

  /// 处理恢复状态
  Stream<TimerState> _mapResumeToState(Resume resume) async* {
    if (state is Paused) {
      _tickerSubscription?.resume();
      yield Running(state.duration);
    }
  }

  /// 处理重置状态
  Stream<TimerState> _mapResetToState(Reset reset) async* {
    _tickerSubscription?.cancel();
    yield Ready(_duration);
  }
}
